﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tracy.DataModel;
using System.Xml;
using System.IO;
namespace Tracy.DataServices
{
    public class TagManager
    {
        XmlDocument _docData;
        XmlElement _rootData;
        public string DataFileName { get { return "Tag.xml"; } }
        public string DataFolder
        {
            get { return "Data"; }
        }
        public string DataRootNodeName
        {
            get { return "tags"; }
        }
        public string DataFilePath
        {
            get { return DataFolder + "\\" + DataFileName; }
        }
        public string SettingsFilePath
        {
            get { return "Settings\\TagSettings.xml"; }
        }
        
        public TagManager()
        {
            LoadItems();
        }

        public void LoadItems()
        {
            if (!Directory.Exists(DataFolder))
            {
                Directory.CreateDirectory(DataFolder);
            }

            _docData = new XmlDocument();
            if (!File.Exists(DataFilePath))
            {
                _rootData = _docData.AppendChild(_docData.CreateElement(DataRootNodeName)) as XmlElement;
                //root.SetAttribute("max-id", "0");
                //doc.Save(FilePath);
            }
            else
            {
                _docData.Load(DataFilePath);
                _rootData = _docData.SelectSingleNode(DataRootNodeName) as XmlElement;
                if (_rootData == null) throw new Exception("Root Node \"" + DataRootNodeName + "\" not found!");
            }

            if(File.Exists(SettingsFilePath)){
                XmlDocument docSettings = new XmlDocument();
                docSettings.Load(SettingsFilePath);
                foreach (XmlElement node in docSettings.SelectNodes("/tag-settings/categories/category"))
                {
                    _categories.Add(node.InnerText);
                }
            }
        }


        public void SaveItems()
        {
            _docData.Save(DataFilePath);
        }

        



        public void SetTags(Entry entry, List<Tag> tags)
        {
            if (entry != null)
            {
                XmlElement entryNode = _rootData.SelectSingleNode(String.Format("entry[@id='{0}']", entry.ID)) as XmlElement;
                if (entryNode != null)
                {
                    //Remove existing entry node
                    _rootData.RemoveChild(entryNode);
                }

                if (tags != null && tags.Count > 0)
                {
                    //Create new entry node
                    entryNode = _docData.CreateElement("entry");
                    _rootData.AppendChild(entryNode);

                    entryNode.SetAttribute("id", entry.ID);

                    //Assign tags
                    foreach (Tag tag in tags)
                    {
                        entryNode.AppendChild(tag.ToXmlNode(_docData));
                    }

                }
                SaveItems();
            }
        }

        public List<Tag> GetTags(Entry entry, string category)
        {
            List<Tag> rtn = new List<Tag>();
            if (entry != null && !String.IsNullOrEmpty(category))
            {
                foreach (XmlNode tagNode in _rootData.SelectNodes(String.Format("entry[@id='{0}']/tag[@category='{1}']", entry.ID, category)))
                {
                    rtn.Add(new Tag(tagNode));
                }
            }
            return rtn;
        }

        public List<string> GetValues(string category)
        {
            List<string> rtn = new List<string>();
            if (!String.IsNullOrEmpty(category))
            {
                foreach (XmlNode tagNode in _rootData.SelectNodes(String.Format("entry/tag[@category='{0}']", category)))
                {
                    if (!rtn.Contains(tagNode.InnerText)) rtn.Add(tagNode.InnerText);
                }
            }
            return rtn;
        }

        public List<Tag> GetTags(Entry entry)
        {
            List<Tag> rtn = new List<Tag>();
            if(entry != null)
            {
                XmlElement entryNode = _rootData.SelectSingleNode(String.Format("entry[@id='{0}']", entry.ID)) as XmlElement;
                if (entryNode != null)
                {
                    foreach (XmlNode tagNode in entryNode.SelectNodes("tag"))
                    {
                        rtn.Add(new Tag(tagNode));
                    }
                }
            }
            return rtn;
        }

        public void AssignTag(Entry entry, Tag tag)
        {
            if (entry != null && tag != null)
            {
                XmlElement entryNode = _rootData.SelectSingleNode(String.Format("entry[@id='{0}']", entry.ID)) as XmlElement;
                if (entryNode == null)
                {
                    entryNode = _docData.CreateElement("entry");
                    _rootData.AppendChild(entryNode);
                    entryNode.SetAttribute("id", entry.ID);
                }

                entryNode.AppendChild(tag.ToXmlNode(_docData));
                SaveItems();
            }
            
        }

        public void RemoveTag(Entry entry, Tag tag)
        {
            if (entry != null && tag != null)
            {
                XmlElement entryNode = _rootData.SelectSingleNode(String.Format("entry[@id='{0}']", entry.ID)) as XmlElement;
                if (entryNode != null)
                {
                    foreach (XmlElement tagNode in entryNode.SelectNodes(String.Format("tag[@category='{0}']", tag.Category)))
                    {
                        if (tagNode.InnerText == tag.Value) entryNode.RemoveChild(tagNode);
                    }
                    
                }
                SaveItems();
            }
           
        }

        private List<string> _categories = new List<string>();
        public List<string> Categories
        {
            get
            {
                return _categories;
            }
        }
    }
}
